bl_info = {
    "name": "360 Image Extractor",
    "author": "ZhiYong Huang",
    "version": (1, 0, 0),
    "blender": (4, 5, 0),
    "location": "View3D > Sidebar > 360 Image Extractor",
    "description": "Extract views from 360 equirectangular images and videos",
    "warning": "",
    "doc_url": "",
    "category": "3D View",
}

import bpy
import os
import math
from bpy.props import StringProperty, BoolProperty, EnumProperty, FloatProperty, IntProperty
from bpy_extras.io_utils import ImportHelper

# Import the image extraction functionality
from . import image_extractor

# Main panel class
class VIEW3D_PT_360ImageExtractor(bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = '360 Image Extractor'
    bl_label = "360 Image Extractor"
    
    def draw(self, context):
        layout = self.layout
        scene = context.scene
        
        # Input section
        box = layout.box()
        box.label(text="Input Settings")
        row = box.row()
        row.operator("image.open_360_image", text="Open 360° Image/Video")
        
        if hasattr(scene, "panorama_image") and scene.panorama_image:
            box.label(text=f"Selected: {os.path.basename(scene.panorama_image)}")
        
        # Output section
        box = layout.box()
        box.label(text="Output Settings")
        box.prop(scene, "output_directory")
        box.prop(scene, "output_format")
        box.prop(scene, "frame_interval")
        
        # Camera section
        box = layout.box()
        box.label(text="Cameras")
        row = box.row()
        row.operator("image.create_directional_cameras", text="Create 12 Directional Cameras")
        
        # Extraction section
        box = layout.box()
        box.label(text="Extract Views")
        row = box.row()
        row.operator("image.extract_views", text="Extract Views")
        row = box.row()
        row.operator("image.extract_video_frames", text="Extract Video Frames")

# Operator to open 360 image
class IMAGE_OT_open_360_image(bpy.types.Operator, ImportHelper):
    bl_idname = "image.open_360_image"
    bl_label = "Open 360° Image/Video"
    bl_description = "Open a 360 equirectangular image or video"
    
    filter_glob: StringProperty(default="*.jpg;*.jpeg;*.png;*.tif;*.tiff;*.mp4", options={'HIDDEN'})
    
    def execute(self, context):
        # Store the file path
        context.scene.panorama_image = self.filepath

        try:
            # Set panorama as environment using the image_extractor module
            image_extractor.set_panorama_as_environment(context.scene.panorama_image)
            
            self.report({'INFO'}, "Panorama set as environment map")
            return {'FINISHED'}
        except Exception as e:
            self.report({'ERROR'}, f"Failed to set environment: {str(e)}")
            return {'CANCELLED'}

        return {'FINISHED'}

# Operator to extract views
class IMAGE_OT_extract_views(bpy.types.Operator):
    bl_idname = "image.extract_views"
    bl_label = "Extract Views"
    bl_description = "Extract multiple views from the 360 image"
    
    def execute(self, context):
        scene = context.scene
        
        if not scene.panorama_image:
            self.report({'ERROR'}, "No panorama image selected")
            return {'CANCELLED'}
        
        if not scene.output_directory:
            self.report({'ERROR'}, "No output directory specified")
            return {'CANCELLED'}
        
        try:
            # Ensure output directory exists
            if not os.path.exists(scene.output_directory):
                os.makedirs(scene.output_directory)
            
            # Extract views using the image_extractor module
            extracted_views = image_extractor.extract_views_from_panorama(
                scene.panorama_image,
                scene.output_directory,
                scene.output_format,
                use_directional_cameras=True
            )
            
            self.report({'INFO'}, f"Extracted {len(extracted_views)} views")
            return {'FINISHED'}
        except Exception as e:
            self.report({'ERROR'}, f"Failed to extract views: {str(e)}")
            return {'CANCELLED'}

# Operator to create directional cameras
class IMAGE_OT_create_directional_cameras(bpy.types.Operator):
    bl_idname = "image.create_directional_cameras"
    bl_label = "Create Directional Cameras"
    bl_description = "Create 12 cameras facing different directions"
    
    def execute(self, context):
        try:
            # Create 8 cameras using the image_extractor module
            cameras = image_extractor.create_cameras_around_scene()
            
            self.report({'INFO'}, f"Created {len(cameras)} directional cameras")
            return {'FINISHED'}
        except Exception as e:
            self.report({'ERROR'}, f"Failed to create cameras: {str(e)}")
            return {'CANCELLED'}


class IMAGE_OT_extract_video_frames(bpy.types.Operator):
    bl_idname = "image.extract_video_frames"
    bl_label = "Extract Video Frames"
    bl_description = "Extract views from multiple frames of a video"
    
    def execute(self, context):
        scene = context.scene
        
        if not scene.panorama_image:
            self.report({'ERROR'}, "No video file selected")
            return {'CANCELLED'}
        
        if not scene.output_directory:
            self.report({'ERROR'}, "No output directory specified")
            return {'CANCELLED'}
        
        # Check if file is a video
        video_path = scene.panorama_image
        if not video_path.lower().endswith(('.mp4', '.avi', '.mov', '.mkv')):
            self.report({'ERROR'}, "Selected file is not a video format")
            return {'CANCELLED'}
        
        try:
            # Ensure output directory exists
            if not os.path.exists(scene.output_directory):
                os.makedirs(scene.output_directory)
            
            # Extract views from video frames
            frame_results = image_extractor.extract_views_from_video_frames(
                video_path,
                scene.output_directory,
                scene.output_format,
                frame_interval=scene.frame_interval,
                use_directional_cameras=True
            )
            
            total_frames = len(frame_results)
            total_views = sum(len(views) for views in frame_results.values())
            
            self.report({'INFO'}, f"Processed {total_frames} frames, extracted {total_views} total views")
            return {'FINISHED'}
        except Exception as e:
            self.report({'ERROR'}, f"Failed to extract video frames: {str(e)}")
            return {'CANCELLED'}

# Register properties
def register():
    bpy.types.Scene.panorama_image = StringProperty(
        name="Panorama Image",
        description="Path to the 360 equirectangular image",
        default=""
    )
    
    bpy.types.Scene.output_directory = StringProperty(
        name="Output Directory",
        description="Directory to save extracted views",
        default="",
        subtype='DIR_PATH'
    )
    
    bpy.types.Scene.output_format = EnumProperty(
        name="Output Format",
        description="Image format for extracted views",
        items=[
            ('PNG', 'PNG', 'PNG format'),
            ('JPEG', 'JPEG', 'JPEG format'),
            ('TIFF', 'TIFF', 'TIFF format')
        ],
        default='JPEG'
    )
    
    bpy.types.Scene.frame_interval = IntProperty(
        name="Frame Interval",
        description="Process every Nth frame (1 = all frames, 2 = every other frame, etc.)",
        default=10,
        min=1,
        max=100
    )
    
    bpy.utils.register_class(VIEW3D_PT_360ImageExtractor)
    bpy.utils.register_class(IMAGE_OT_open_360_image)
    bpy.utils.register_class(IMAGE_OT_extract_views)
    bpy.utils.register_class(IMAGE_OT_extract_video_frames)
    bpy.utils.register_class(IMAGE_OT_create_directional_cameras)  # Add this line

# Unregister properties
def unregister():
    del bpy.types.Scene.frame_interval
    del bpy.types.Scene.output_format
    del bpy.types.Scene.output_directory
    del bpy.types.Scene.panorama_image
    
    bpy.utils.unregister_class(IMAGE_OT_create_directional_cameras)
    bpy.utils.unregister_class(IMAGE_OT_extract_video_frames)
    bpy.utils.unregister_class(IMAGE_OT_extract_views)
    bpy.utils.unregister_class(IMAGE_OT_open_360_image)
    bpy.utils.unregister_class(VIEW3D_PT_360ImageExtractor)

if __name__ == "__main__":
    register()